<template>
    <el-form
        ref="form"
        :model="form"
        v-bind="$attrs"
        v-on="$listeners">
        <el-row v-for="{title,tip,items} in groups" :key="title" type="flex" justify="start"
                style="flex-wrap: wrap; flex-direction: row" :gutter="10">
            <el-col :span="24">
                <form-title :title="title" :tip="tip"/>
                <slot name="titleRight"></slot>
            </el-col>
            <el-col v-for="{prop,span,label,event,labelWidth,...option} in items" :key="prop" :span="span?span:24">
                <el-form-item :label-width="labelWidth" :label="label" :prop="prop">
                    <form-item-factory v-model="form[prop]" v-bind="option" v-on="event"/>
                </el-form-item>
            </el-col>
        </el-row>
    </el-form>
</template>

<script>
import FormTitle from '@/components/Form/components/formTitle'
import {setAsVal} from '@/utils/formUtils'
export default {
    name: 'DynamicForm',
    components: {
        FormTitle
    },
    props: {
        // 表单配置
        formGroups: {
            type: Array,
            default: () => []
        },
        value: {
            type: Object,
            default: () => ({})
        }
    },
    data () {
        return {
            form: {}
        }
    },
    watch: {
        // form: {
        //   handler (newV, oldV) {
        //     this.$emit('input', newV)
        //   }
        // },
        value: {
            // deep: true,
            immediate: true,
            handler (newV) {
                // console.log(newV)
                this.form = newV
            }
        }
    },
    computed: {
        groups () {
            return this.formGroups.reduce((pre, formGroup) => {
                if (formGroup.hide === true) return pre
                formGroup.items = formGroup.items.reduce((pre, item) => {
                    const {hide, bind, prop} = item
                    if (hide === true) return pre
                    // 深层次数据绑定
                    if (bind) {
                        this.$watch('form.' + prop, (n, o) => {
                            if (n !== o) {
                                setAsVal(this.form, bind, n)
                            }
                        })
                        this.$watch('form.' + bind, (n, o) => {
                            if (n !== o) {
                                this.$set(this.form, prop, n)
                            }
                        })
                    }
                    pre.push(item)
                    return pre
                }, [])
                pre.push(formGroup)
                return pre
            }, [])
        }
    },
    mounted () {
        this.form = this.value
    },
    methods: {
        validate () {
            return new Promise((resolve) => {
                this.$refs.form.validate((validate) => {
                    resolve(validate)
                })
            })
        },
        clearValidate () {
            this.$refs.form.clearValidate()
        },
        validateField (prop) {
            return new Promise((resolve) => {
                this.$refs.form.validateField(prop, (errorMessage) => {
                    resolve(errorMessage)
                })
            })
        },
        resetForm () {
            Object.keys(this.form).forEach(key => {
                this.form[key] = undefined
            })
        }
    }
}
</script>
<style>
/*
  动态组件挂载时间选择器会出现弹出框被对话框蒙版遮住的问题
*/
.el-date-picker,.el-cascader__dropdown{
    z-index:9999!important;
}
</style>
<style scoped lang="scss">
.el-col{
    border:1px solid transparent;
}
::v-deep .el-input-number .el-input__inner {
    text-align: left;
}
</style>
